package cel;

import static robocode.util.Utils.normalRelativeAngleDegrees;
import java.awt.Color;
import robocode.AdvancedRobot;
import robocode.HitByBulletEvent;
import robocode.HitRobotEvent;
import robocode.HitWallEvent;
import robocode.Rules;
import robocode.ScannedRobotEvent;

/**
 * Implementation of the WayFarar Robot. The robot moves back an forth along an axis. When the robot
 * gets hit with a robot, it turns 90 degrees and travels back and fourth on that access while
 * scanning for enemies and attacking them.
 * 
 * @author Elmar Carillo
 */
public class WayFarer extends AdvancedRobot {
  // The longest length of the the battlefield (Diagonal).
  private double longestLength;
  // Ensures that a bullet is fired every other turn.
  private boolean restFire;

  /**
   * Starts the robot.
   */
  public void run() {
    robotColors();
    findLongestLength();
    turnLeft(getHeading() + 90);
    setMaxVelocity(Rules.MAX_VELOCITY);
    restFire = false;
    while (true) {
      setAhead(10000);
      // Scan for enemies,
      setTurnRadarRight(90);
      execute();
    }
  }

  /**
   * Sets the colors of the robot.
   */
  private void robotColors() {
    // Body = Gray; Gun = White; Radar = White; Bullet = YELLOW; Scan Arc = White
    setColors(Color.GRAY, Color.BLACK, Color.WHITE, Color.YELLOW, Color.WHITE);
  }

  /**
   * When the robot hits a wall, it reverses its direction by turning right 180 degrees.
   * 
   * @param hwe information that the robot hit a wall.
   */
  public void onHitWall(HitWallEvent hwe) {
    // Reverse the robot's direction by turning around 180 degrees.
    turnRight(180);
    // Set False to shoot next fire.
    restFire = false;
    execute();
  }

  /**
   * When the robot hits an enemy aim and shoot at the enemy and move back.
   * 
   * @param hre hit contains information about the enemy robot, e.g. its location.
   */
  public void onHitRobot(HitRobotEvent hre) {
    // Reverse the robot's direction by turning around 180 degrees.
    turnGunRight(normalRelativeAngleDegrees(hre.getBearing() + (getHeading() - getGunHeading())));
    fire(Rules.MAX_BULLET_POWER);
    turnRight(90);
    // Set False to shoot next fire.
    restFire = false;
    back(200);
  }

  /**
   * When the robot finds an enemy, it points it's gun towards the enemy and fires according to
   * distance. If the enemy is less than 80 pixels close, move away.
   * 
   * @param sre Information about the scanned robot.
   */
  public void onScannedRobot(ScannedRobotEvent sre) {
    // Turn robot towards the enemy and assume it is still moving
    if (sre.getDistance() < 80) {
      // Turn towards enemy.
      turnRight(sre.getBearing());
      // Move away 100 pixels
      ahead(sre.getDistance() - 100);
      // Scan for enemies,
      setTurnRadarRight(90);
      // Set False to shoot next fire.
      restFire = false;
    }
    turnGunRight(normalRelativeAngleDegrees(sre.getBearing() + (getHeading() - getGunHeading())));
    if (restFire) {
      // Set False to shoot next fire.
      restFire = false;
    }
    else {
      // If enemy is located less than 25% of longest length.
      if (sre.getDistance() <= longestLength * 0.25) {
        // Fire guns at maximum power.
        fire(Rules.MAX_BULLET_POWER);
      }
      // If enemy is located between 25% and 50% of longest length.
      else if (sre.getDistance() <= longestLength * 0.50) {
        // Fire guns at 2/3 of maximum power.
        fire(Rules.MAX_BULLET_POWER * (2.0 / 3.0));
      }
      // If enemy is located between 50% and 75% of longest length.
      else if (sre.getDistance() <= longestLength * 0.75) {
        // Fire guns at 1/3 of maximum power.
        fire(Rules.MAX_BULLET_POWER * (1.0 / 3.0));
      }
      // If enemy is located between 75% of longest length or further.
      else {
        // Fire guns at minimal power.
        fire(Rules.MIN_BULLET_POWER);
      }
      // Set true to skip next fire.
      restFire = true;
    }
  }

  /**
   * When the robot is hit by a bullet, turn right 90 degrees.
   * 
   * @param hbbe hit contains information about the enemy robot bullet.
   */
  public void onHitByBullet(HitByBulletEvent hbbe) {
    turnRight(90);
    execute();
  }

  /**
   * Finds the longest length of the battlefield.
   */
  private void findLongestLength() {
    // Get the X-Coordinate of the upper right corner of the battlefield.
    double xLength = getBattleFieldWidth();
    // Get the Y-Coordinate of the upper right corner of the battlefield.
    double yLength = getBattleFieldHeight();
    // The length of the diagonal of the battlefield.
    longestLength = Math.sqrt(xLength * xLength + yLength * yLength);
  }
}